﻿
//Define Namespace
window.ArthurGraus = window.ArthurGraus || {};
"use strict";
/*var YAHOO = {};
YAHOO.util = {};
YAHOO.util.ScriptNodeDataSource = {};*/
var YAHOO = {
    Finance: {
        SymbolSuggest: {}
    }
};


function watchListDetail(ID, Title, TickerSymbol,select) {
    var self = this;
    self.id = ID;
    self.Title = Title;
    self.TickerSymbol = TickerSymbol;
    self.selected = ko.observable(select);
    self.data = null;
}
function timeLine(duration) {
    var self = this;
    self.duration = duration;
    self.selected = ko.observable(false);
}

function autocompleteResult(title,symbol,type,exchDisp) {
    var self = this;
    self.title = title;
    self.symbol = symbol;
    self.type = type;
    self.exchDisp = exchDisp;
    self.resultInString = function () {
        var result = self.symbol + " " + self.title + " (" + self.type + " - " + self.exchDisp + ")";
        return result;
    }
}

ArthurGraus.StockDashboard = function () {
    var self = this;
    self.isPositiveResult = ko.observable(false);
    self.stockDifference = ko.observable(0);
    self.stockDifferenceRatio = ko.observable(null);
    self.currentStockPrice = ko.observable(0);
    self.hasResults = ko.observable(true);
    self.countChartProgress = 0;
    self.ItemCount = 0;
    self.firstEMADescript = "SMA 50 days period";
    self.secondEMADescript = "SMA 200 days period";
    self.currentCompanyTitle = ko.observable();
    self.inputTickerSymbol = ko.observable();
    self.autocompleteResults = ko.observableArray();
    self.tickerSymbolReserve = new Array();
    self.currentAddorRemoveTickerSymbol = null;
    self.filterId = 0;
    self.appWebUrl = "";
    self.hostWebUrl = "";
    self.executor = null;
    self.appWebUrl = null;
    self.executorAppWeb = null;
    self.appWebContext = null;
    self.appWeb = null;
    self.watchList = null;
    self.connectionString = "";
    self.quotes = new Object();
    self.watchLDetail = ko.observableArray();
    self.testArray = ko.observableArray();
    self.currentTickerSymbol = null;
    self.candleStickTimeline = ko.observableArray();
    self.showByWeeks = ko.observable(false);
    self.isShowVolumeChart = ko.observable(true);
    self.isShowCandleStickChart = ko.observable(true);
    self.isShowIRSChart = ko.observable(true);

    self.initialize = function () {
        self.appWebContext = new SP.ClientContext(self.appWebUrl);
        self.executorAppWeb = new SP.ProxyWebRequestExecutorFactory(self.appWebUrl);
        self.appWebContext.set_webRequestExecutorFactory(self.executorAppWeb);

        self.appWeb = self.appWebContext.get_web();
        self.watchList = self.appWeb.get_lists().getByTitle('WatchList');
        for (var i = 1; i < 4; i++) {
            self.candleStickTimeline.push(new timeLine(i))
        }
        self.candleStickTimeline.push(new timeLine(4))
        self.candleStickTimeline.push(new timeLine(6))
        self.candleStickTimeline()[2].selected(true);
        var camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml(
            '<View/>'
        );
        self.watchListItems = self.watchList.getItems(camlQuery);

        self.appWebContext.load(self.watchListItems);
        self.appWebContext.executeQueryAsync(self.getWatchListItems_completed, self.errorHandler);

    };

    self.getWatchListItems_completed = function (sender, args) {

        var listItemEnumerator = self.watchListItems.getEnumerator();
        var listItemInfo = "";
        while (listItemEnumerator.moveNext()) {
            var oListItem = listItemEnumerator.get_current();
            listItemInfo += '\nID: ' + oListItem.get_id() +
                '\nTitle: ' + oListItem.get_item('Title') +
                '\nBody: ' + oListItem.get_item('TickerSymbol');
            self.watchLDetail.push(new watchListDetail( oListItem.get_id(), oListItem.get_item('Title'), oListItem.get_item('TickerSymbol'),false))
        }
        
        if (self.watchLDetail().length > 0) {
            self.onChangeTicketSymbol(self.watchLDetail()[0]);
        }

        $("#autoSuggestInput").autocomplete({
            source: function (request, response) {
                var query = request.term;
                self.autocompleteResults.removeAll();
                $.ajax({
                    type: "GET",
                    url: "https://autoc.finance.yahoo.com/autoc",
                    data: { query: query },
                    dataType: "jsonp",
                    jsonp: "callback",
                    jsonpCallback: "YAHOO.Finance.SymbolSuggest.ssCallback",
                });
                // call back function
                YAHOO.Finance.SymbolSuggest.ssCallback = function (data) {
                    var suggestions = [];
                    //alert(JSON.stringify(data.ResultSet.Result));                            
                    $.each(data.ResultSet.Result, function (i, val) {
                        self.autocompleteResults.push(new autocompleteResult(val.name, val.symbol, val.type, val.exchDisp));
                        suggestions.push(val.symbol +
                                " " + val.name +
                                " (" + val.type +
                                " - " + val.exchDisp + ")");
                    });

                    response(suggestions);
                }
            },
            minLength: 1,
            select: function (e, ui) {
                //alert(ui.item.value.split("#")[1]);
                for (var result in self.autocompleteResults()) {
                    if (self.autocompleteResults()[result].resultInString() == ui.item.value) {
                        self.inputTickerSymbol(self.autocompleteResults()[result].symbol);
                        self.currentAddorRemoveTickerSymbol = new watchListDetail(null, self.autocompleteResults()[result].title, self.autocompleteResults()[result].symbol, false);
                    }
                }

            },
        });

    };

    self.loadTicketSymbol = function (TickerSymbol) {

        var url = "../Services/StockDashboardService.svc/GetQuotes/{symbol}?s={startDate}&e={endDate}&c={connectionString}";
        var endDate = Date.today();
        var startDate = Date.today().addDays(-350);
        url = url.replace("{symbol}", encodeURIComponent(TickerSymbol));
        url = url.replace("{connectionString}", encodeURIComponent(self.connectionString));
        url = url.replace("{startDate}", encodeURIComponent(startDate.format('yyyy-mm-dd')));
        url = url.replace("{endDate}", encodeURIComponent(endDate.format('yyyy-mm-dd')));

        $.ajax({
            type: "GET",
            url: url,
            dataType: "jsonp",
            crossDomain: true,
            success: function (results) {
                if (results != null && results.length > 0) {
                    self.quotes[results[0].Symbol] = results;
                    //alert("Loaded quotes for: " + results[0].Symbol);
                    self.GetResult(results);
                    //Bind to chart
                }
            },
            error: function (result) {
                alert('error!');

            }
        });

        //}
        //}

    };

    self.GetResult = function (results) {
        for (var ListDetail in self.watchLDetail()) {
            if (results[0].Symbol == self.watchLDetail()[ListDetail].TickerSymbol) {
                self.watchLDetail()[ListDetail].data = results;
            }
            if (results[0].Symbol == self.watchLDetail()[0].TickerSymbol) {
                self.onChangeTicketSymbol(self.watchLDetail()[0]);
            }
        }


    }


    self.onChangeTicketSymbol = function (data) {
        for (var num in self.watchLDetail()) {
            self.watchLDetail()[num].selected(false);
        }
        data.selected(true);
        self.currentTickerSymbol = data.TickerSymbol;
        self.getQuotesAndDraw();
        //self.showCandleStickChart(data.data);
    }

    self.onAddorRemoveTicketSymbol = function () {
        //$("#MainWindow").hide();
        self.tickerSymbolReserve=[]
        for (var num in self.watchLDetail()) {
            self.tickerSymbolReserve.push(self.watchLDetail()[num])
        }
        $("#AddorRemoveWatchListBox").show();
    }

    self.onCloseAddorRemoveWatchListBox = function () {
        $("#AddorRemoveWatchListBox").hide();
        //$("#MainWindow").show();
    }

    self.onOkAddorRemoveWatchListBox = function () {
        $("#AddorRemoveWatchListBox").hide();
        //$("#MainWindow").show();
    }

    self.onCancelAddorRemoveWatchListBox = function () {
        $("#AddorRemoveWatchListBox").hide();
        //$("#MainWindow").show();
        self.ItemCount = self.watchLDetail().length;
        for (var num in self.watchLDetail()) {
            var oListItem = self.watchList.getItemById(self.watchLDetail()[num].id);
            oListItem.deleteObject();
            self.appWebContext.executeQueryAsync(self.onDeleteComplete);
        }
        self.watchLDetail.removeAll();
        

    }
    self.onDeleteComplete = function () {
        self.ItemCount -= 1;
        if (self.ItemCount == 0) {
            self.onReAddWatchListItems();
        }
    }

    self.onReAddWatchListItems = function () {
        for (var num in self.tickerSymbolReserve) {
            self.currentAddorRemoveTickerSymbol = new watchListDetail(self.tickerSymbolReserve[num].id, self.tickerSymbolReserve[num].Title, self.tickerSymbolReserve[num].TickerSymbol, self.tickerSymbolReserve[num].selected);
            var itemCreateInfo = new SP.ListItemCreationInformation();
            self.watchListItem = self.watchList.addItem(itemCreateInfo);
            var existTicketSymbol = false;
            for (var number in self.watchLDetail()) {
                if (self.watchLDetail()[number].TickerSymbol == self.currentAddorRemoveTickerSymbol.TickerSymbol)
                    existTicketSymbol = true;
            }
            if (!existTicketSymbol && self.currentAddorRemoveTickerSymbol != null) {
                self.watchListItem.set_item('Title', self.currentAddorRemoveTickerSymbol.Title);
                self.watchListItem.set_item('TickerSymbol', self.currentAddorRemoveTickerSymbol.TickerSymbol);
                self.watchListItem.update();
                //self.appWebContext.load(self.watchListItem);
                self.watchLDetail.push(self.currentAddorRemoveTickerSymbol);
                self.currentAddorRemoveTickerSymbol = null;
            }
            
        }
        self.appWebContext.executeQueryAsync(self.getQuotesAndDraw);
    }

    self.onAddWatchListItem = function () {
        var newTicketSymbol = self.inputTickerSymbol();
        var itemCreateInfo = new SP.ListItemCreationInformation();
        self.watchListItem = self.watchList.addItem(itemCreateInfo);
        var existTicketSymbol = false;
        for (var num in self.watchLDetail()) {
            if (self.watchLDetail()[num].TickerSymbol == newTicketSymbol)
                existTicketSymbol = true;
        }
        if (newTicketSymbol != null && !existTicketSymbol && self.currentAddorRemoveTickerSymbol==null)
        {
            self.watchListItem.set_item('Title', newTicketSymbol);
            self.watchListItem.set_item('TickerSymbol', newTicketSymbol);
            self.watchListItem.update();
            self.appWebContext.load(self.watchListItem);
            self.appWebContext.executeQueryAsync(self.onAddWatchListItemSucceeded);
        }
        else if (newTicketSymbol != null && !existTicketSymbol && self.currentAddorRemoveTickerSymbol != null) {
            self.watchListItem.set_item('Title', self.currentAddorRemoveTickerSymbol.Title);
            self.watchListItem.set_item('TickerSymbol', self.currentAddorRemoveTickerSymbol.TickerSymbol);
            self.watchListItem.update();
            self.appWebContext.load(self.watchListItem);
            self.appWebContext.executeQueryAsync(self.onAddWatchListItemSucceeded);
            self.currentAddorRemoveTickerSymbol = null;
        }
        self.inputTickerSymbol("");
        
    }

    self.onAddWatchListItemSucceeded = function () {
        self.watchLDetail.push(new watchListDetail(self.watchListItem.get_id(), self.watchListItem.get_item('Title'), self.watchListItem.get_item('TickerSymbol'), false));
    }
    
    self.onDeleteWatchListItem = function (watchListItem) {
        var oListItem = self.watchList.getItemById(watchListItem.id);
        oListItem.deleteObject();
        self.appWebContext.executeQueryAsync();
        self.watchLDetail.remove(watchListItem);
    }

    self.onChangeTimeLine = function (data) {
        for (var num in self.candleStickTimeline()) {
            self.candleStickTimeline()[num].selected(false);
        }
        data.selected(true);
        self.getQuotesAndDraw();
        //self.showCandleStickChart(data.data);
    }

    self.onChangeToDay = function () {
        self.showByWeeks(false);
        self.candleStickTimeline.removeAll()
        for (var i = 1; i < 4; i++) {
            self.candleStickTimeline.push(new timeLine(i))
        }
        self.candleStickTimeline.push(new timeLine(4))
        self.candleStickTimeline.push(new timeLine(6))
        self.candleStickTimeline()[2].selected(true);
        self.firstEMADescript = "SMA 50 days period";
        self.secondEMADescript = "SMA 200 days period";
        self.getQuotesAndDraw();
    }

    self.onChangeToWeek = function () {
        self.showByWeeks(true);
        self.candleStickTimeline.removeAll()
        self.candleStickTimeline.push(new timeLine(3))
        self.candleStickTimeline.push(new timeLine(6))
        self.candleStickTimeline.push(new timeLine(9))
        self.candleStickTimeline.push(new timeLine(12))
        self.candleStickTimeline()[2].selected(true);
        self.firstEMADescript = "SMA 5 weeks period";
        self.secondEMADescript = "SMA 20 weeks period";
        self.getQuotesAndDraw();
    }

    self.onChangeCandleStick = function () {
        if (self.isShowCandleStickChart())
            self.isShowCandleStickChart(false);
        else
            self.isShowCandleStickChart(true);
        self.getQuotesAndDraw();
    }

    self.onChangeIRS = function () {
        if (self.isShowIRSChart())
            self.isShowIRSChart(false);
        else
            self.isShowIRSChart(true);
        self.getQuotesAndDraw();
    }

    self.onChangeVolume = function () {
        if (self.isShowVolumeChart())
            self.isShowVolumeChart(false);
        else
            self.isShowVolumeChart(true);
        self.getQuotesAndDraw();
    }

    self.getQuotesAndDraw = function () {
        self.Wait();
        self.getLastestUpdate();
        var url = "../Services/StockDashboardService.svc/GetQuotes/{symbol}?s={startDate}&e={endDate}&c={connectionString}";

        //var listItemEnumerator = self.watchListItems.getEnumerator();
        var listItemInfo = "";
        /*while (listItemEnumerator.moveNext()) {
            var oListItem = listItemEnumerator.get_current();

            if (oListItem.get_item('TickerSymbol') == "TOM2.AS") {*/


        var endDate = Date.today();
        var startDate = Date.today().addDays(-600);
        for (var num in self.watchLDetail()) {
            if (self.watchLDetail()[num].TickerSymbol == self.currentTickerSymbol)
                self.currentCompanyTitle(self.watchLDetail()[num].Title);
        }
        
        //url = url.replace("{symbol}", encodeURIComponent(oListItem.get_item('TickerSymbol')));
        url = url.replace("{symbol}", encodeURIComponent(self.currentTickerSymbol));
        url = url.replace("{connectionString}", encodeURIComponent(self.connectionString));
        url = url.replace("{startDate}", encodeURIComponent(startDate.format('yyyy-mm-dd')));
        url = url.replace("{endDate}", encodeURIComponent(endDate.format('yyyy-mm-dd')));

        $.ajax({
            type: "GET",
            url: url,
            dataType: "jsonp",
            crossDomain: true,
            success: function (results) {
                if (results != null && results.length > 0) {
                    self.hasResults(true);
                    self.quotes[results[0].Symbol] = results;
                    self.countChartProgress = 0;
                    if (self.isShowCandleStickChart())
                        self.countChartProgress += 1;
                    if (self.isShowVolumeChart())
                        self.countChartProgress += 1;
                    if (self.isShowIRSChart())
                        self.countChartProgress += 1;
                    if (self.isShowCandleStickChart())
                        self.showCandleStickChart(results);
                    if (self.isShowVolumeChart())
                        self.showVolumeChart(results);
                    if (self.isShowIRSChart())
                        self.showRSIChart(results);
                    if(!self.isShowIRSChart()&&!self.isShowVolumeChart()&&!self.isShowCandleStickChart())
                        self.CancelWait()
                }
                else {
                    self.hasResults(false);
                    self.CancelWait();
                }
            },
            error: function (result) {
                alert('error!');
                self.CancelWait();
            }
        });

        //}
        //}

    };

    self.formatJSONDate = function(jsonDate) {
        var newDate = dateFormat(jsonDate.substring(6, 19)*1, "mm/dd");
        return newDate;
    }

    self.formatDateFull = function (jsonDate) {
        var newDate = dateFormat(jsonDate.substring(6, 19) * 1, "mm/dd/yyyy");
        return newDate;
    }

    self.Wait = function () {
        $("#waitingLayer").show();
        $("#waitingdiv").show();
    }
    self.CancelWait = function () {
        $("#waitingLayer").hide();
        $("#waitingdiv").hide();
    }

    self.DoneChoose = function () {
        $("#MainWindow").show();
        $("#ChartConfig").hide();
    }

    self.showRSIChart = function (result) {
        //self.Wait();
        var dataForTable = new Array();
        var data = new google.visualization.DataTable();
        var RSI14 = self.relativeStrengthIndex(14);
        data.addColumn('string', "Date");
        data.addColumn('number', "RSI");
        data.addColumn('number', "thresholeBottom");
        data.addColumn('number', "thresholeTop");
        var period = 1;
        for (var time in self.candleStickTimeline()) {
            if (self.candleStickTimeline()[time].selected())
                period = self.candleStickTimeline()[time].duration;
        }
        var startChartDate = Date.today().addDays(-30 * period);
        var weekDaysCollection = new Array()
        var weekCollection = new Array()
        var currentDate = new Date(self.formatDateFull(result[0].Date));
        if (self.showByWeeks()) {
            while (currentDate <= Date.today()) {
                if (!currentDate.isWeekday()) {
                    if (weekDaysCollection.length > 0) {
                        weekCollection.push(weekDaysCollection)
                        weekDaysCollection = [];
                    }
                    currentDate.next().monday();
                }
                weekDaysCollection.push(new Date(currentDate));
                currentDate.addDays(1);

            }
            resultByWeeks = self.getVolumeRSIWeek(weekCollection, result, false);
            for (var num in resultByWeeks) {
                try {
                    if (resultByWeeks[num][0].getTime() < startChartDate.getTime()) {
                        RSI14(resultByWeeks[num][1])
                    }
                    else {
                        var individualArray = [resultByWeeks[num][0].toString('M/d'), RSI14(resultByWeeks[num][1]),30,70];
                        dataForTable.push(individualArray);
                    }

                }
                catch (err) {

                }
            }
        }
        else {
            for (var num in result) {
                try {
                    var currentResultTime = new Date(self.formatDateFull(result[num].Date));
                    if (currentResultTime < startChartDate.getTime()) {
                        RSI14(result[num].Close)
                    }
                    else {
                        var individualArray = [self.formatJSONDate(result[num].Date), RSI14(result[num].Close), 30, 70];
                        dataForTable.push(individualArray);
                    }

                }
                catch (err) {

                }
            }
        }

        data.addRows(dataForTable);
        var options = {
            legend: 'none',
            vAxis: {
                title: "RSI",
                ticks: [10,30,50,70,90],
                maxValue: 100,
                minValue: 0,
                textStyle:{fontSize:9}
            },
            hAxis: {
                //title: "Time",
                //slantedText: true,
                //slantedTextAngle: 90,
                textPosition: 'none'
            },
            chartArea: {
                width: 850,
                height:80
            },
            seriesType: "line",
            series: { 1: { type: "line", color: "Green", lineWidth: 0.8 }, 2: { type: "line", color: "Red", lineWidth: 0.8 } }
        };

        var chart = new google.visualization.ComboChart($('#chart_RSI_div')[0]);
        chart.draw(data, options);
        //self.CancelWait();
        self.countChartProgress -= 1;
        if (self.countChartProgress==0)
            self.CancelWait();
    }

    self.showVolumeChart = function (result) {
        //self.Wait();
        var dataForTable = new Array();
        var data = new google.visualization.DataTable();
        data.addColumn('string', "Date");
        data.addColumn('number', "Volume");
        var period = 1;
        for (var time in self.candleStickTimeline()) {
            if (self.candleStickTimeline()[time].selected())
                period = self.candleStickTimeline()[time].duration;
        }
        var startChartDate = Date.today().addDays(-30 * period);
        var weekDaysCollection = new Array()
        var weekCollection = new Array()
        var currentDate = new Date(startChartDate);
        if (self.showByWeeks()) {
            while (currentDate <= Date.today()) {
                if (!currentDate.isWeekday()) {
                    if (weekDaysCollection.length > 0) {
                        weekCollection.push(weekDaysCollection)
                        weekDaysCollection = [];
                    }
                    currentDate.next().monday();
                }
                weekDaysCollection.push(new Date(currentDate));
                currentDate.addDays(1);

            }
            resultByWeeks = self.getVolumeRSIWeek(weekCollection, result, true);
            for (var num in resultByWeeks) {
                try {
                    var individualArray = [resultByWeeks[num][0].toString('M/d'), resultByWeeks[num][1]];
                    dataForTable.push(individualArray);
                }
                catch (err) {

                }
            }
        }
        else {
            for (var num in result) {
                var currentResultTime = new Date(self.formatDateFull(result[num].Date));
                if (currentResultTime.getTime() >= startChartDate.getTime()) {
                    var individualArray = [self.formatJSONDate(result[num].Date), result[num].Volume];
                    dataForTable.push(individualArray);
                }
            }
        }
        data.addRows(dataForTable);
        var options = {
            legend: 'none',
            vAxis: { title: "Volume" },
            hAxis: {
                //title: "Time",
                //slantedText: true,
                //slantedTextAngle: 90,
                textPosition:'none'
            },
            chartArea: {
                width: 850,
                height:80
            },
            seriesType: "bars"
        };

        var chart = new google.visualization.ComboChart($('#chart_volume_div')[0]);
        chart.draw(data, options);
        //self.CancelWait();
        self.countChartProgress -= 1;
        if (self.countChartProgress == 0)
            self.CancelWait();
    }

    self.showCandleStickChart = function (result) {
        //self.Wait();
        var dataForTable = new Array();
        var resultByWeeks = null;
        var resultForCandleStickperiod = new Array();
        var data = new google.visualization.DataTable();
        data.addColumn('string', "Date");
        data.addColumn('number', "Low");
        data.addColumn('number', "Open");
        data.addColumn('number', "Close");
        data.addColumn('number', "High");
        data.addColumn('number', self.firstEMADescript);
        data.addColumn('number', self.secondEMADescript);

        var period = 1;
        for (var time in self.candleStickTimeline()){
            if(self.candleStickTimeline()[time].selected())
                period=self.candleStickTimeline()[time].duration;
        }
        var startChartDate = Date.today().addDays(-30 * period);
        if (self.showByWeeks()) {
            //self.Wait();
            var sma5 = self.movingAverage(5);
            var sma20 = self.movingAverage(20);
            var weekDaysCollection = new Array()
            var weekCollection = new Array()
            var currentDate = new Date(self.formatDateFull(result[0].Date));
            while (currentDate <= Date.today()) {
                if (!currentDate.isWeekday()) {
                    if (weekDaysCollection.length > 0) {
                        weekCollection.push(weekDaysCollection)
                        weekDaysCollection = [];
                    }
                    currentDate.next().monday();
                }
                weekDaysCollection.push(new Date(currentDate));
                currentDate.addDays(1);

            }
            resultByWeeks = self.getResultPerWeek(weekCollection, result);
            for (var num in resultByWeeks) {
                if (resultByWeeks[num][0].getTime() < startChartDate.getTime()) {
                    sma5(resultByWeeks[num][3]);
                    sma20(resultByWeeks[num][3]);
                }
                else {
                    try{
                        var individualArray = [resultByWeeks[num][0].toString('M/d'), resultByWeeks[num][1], resultByWeeks[num][2], resultByWeeks[num][3], resultByWeeks[num][4], sma5(resultByWeeks[num][3]), sma20(resultByWeeks[num][3])];
                        dataForTable.push(individualArray);
                    }
                    catch (err) {

                    }
                }
            }
        }
        else {
            var sma50 = self.movingAverage(50);
            var sma200 = self.movingAverage(200);
            for (var num in result) {
                var currentResultTime = new Date(self.formatDateFull(result[num].Date));
                if (currentResultTime.getTime() < startChartDate.getTime()) {
                    sma50(result[num].Close);
                    sma200(result[num].Close);
                }
                else {
                    var individualArray = [self.formatJSONDate(result[num].Date), result[num].Low, result[num].Open, result[num].Close, result[num].High, sma50(result[num].Close), sma200(result[num].Close)];
                    dataForTable.push(individualArray);
                }
            }
        }
        data.addRows(dataForTable);
        var options = {
            //legend: 'none',
            candlestick: {      
                hollowIsRising: true,
                risingColor: { color: "Green", fill: "Green", stroke: "Green", strokeWidth: 2 },
                fallingColor: { color: "Red", fill: "Red", stroke: "Red", strokeWidth: 2 }
            },
            seriesType: "candlesticks",
            hAxis: {
                slantedText: true,
                slantedTextAngle: 90
            },
            legend: { position: 'top', textStyle: { font: 'Segoe UI Light', fontSize: 11 } },
            chartArea:{
                width: 850,
                //height:390
            },
            //series: { 6: { type: "line" } },
            series: { 0: { color: "Black", visibleInLegend: false,strokeWidth:1}, 1: { type: "line", color: "Blue" }, 2: { type: "line", color: "Purple" } }

        };

        var chart = new google.visualization.ComboChart($('#chart_div')[0]);
        chart.draw(data, options);
        //self.CancelWait();
        self.countChartProgress -= 1;
        if (self.countChartProgress == 0)
            self.CancelWait();
    }

    self.getResultPerWeek = function (weeks, result) {
        var resultByWeeks = new Array();
        for (var numWeek in weeks) {
            var Open = null;
            var Close = null;
            var Lowest = null;
            var Highest = null;
            var LastDate = null;
            var isFirstDayInWeek = true;
            var numb = 0;
            for(var numDay in weeks[numWeek]){
                for (var num=numb;num<result.length;num++) {
                    var currentResultTime = new Date(self.formatDateFull(result[num].Date));
                    if (currentResultTime.getTime() == weeks[numWeek][numDay].getTime()) {
                        if (LastDate == null || LastDate.getTime() < weeks[numWeek][numDay].getTime()) {
                            LastDate = weeks[numWeek][numDay];
                            Close = result[num].Close;
                        }
                        if (isFirstDayInWeek) {
                            Open = result[num].Open;
                            isFirstDayInWeek = false;
                        }
                        if (Lowest == null || Lowest > result[num].Low) {
                            Lowest = result[num].Close;
                        }
                        if (Highest == null || Highest < result[num].High) {
                            Highest = result[num].High;
                        }
                        numb = num;
                        break;
                    }
                }
            }
            resultByWeeks.push([LastDate, Lowest, Open, Close, Highest])
        }
        return resultByWeeks;
        
    }

    self.getVolumeRSIWeek = function (weeks, result,isVolume) {
        var resultByWeeksVolume = new Array();
        var resultByWeeksRSI = new Array();
        var numb = 0;
        for (var numWeek in weeks) {
            var Volume = 0;
            var LastDate = null;
            var CloseLastDay = null;
            for (var numDay in weeks[numWeek]) {
                for (var num = numb; num < result.length; num++) {
                    var currentResultTime = new Date(self.formatDateFull(result[num].Date));
                    if (currentResultTime.getTime() == weeks[numWeek][numDay].getTime()) {
                        if (LastDate == null || LastDate.getTime() < weeks[numWeek][numDay].getTime()) {
                            LastDate = weeks[numWeek][numDay];
                            CloseLastDay = result[num].Close;
                        }
                        Volume += result[num].Volume;
                        numb = num;
                        break;
                    }
                }
            }
            resultByWeeksVolume.push([LastDate, Volume]);
            resultByWeeksRSI.push([LastDate, CloseLastDay]);
        }
        if(isVolume)
            return resultByWeeksVolume;
        else
            return resultByWeeksRSI;

    }


    self.relativeStrengthIndex = function (period) {
        var nums = [];
        var avgGain = 0;
        var avgLoss = 0;
        return function (num) {
            nums.push(num);
            if (nums.length > (period+1))
                nums.splice(0, 1);  // remove the first element of the array
            if (nums.length == (period+1) && avgGain == 0 && avgLoss == 0)
            {
                var CurrentValue = 0;
                var gainCollection = new Array();
                var lossCollection = new Array();
                for (var i in nums) {
                    if (i == 0)
                        CurrentValue = nums[i];
                    else {
                        if (nums[i] > CurrentValue)
                            gainCollection.push(nums[i] - CurrentValue);
                        else if (nums[i] < CurrentValue)
                            lossCollection.push(CurrentValue - nums[i]);
                        CurrentValue = nums[i];
                    }
                }
                var sum = 0;
                for (var i = 0; i < gainCollection.length; i++) {
                    sum += gainCollection[i];
                }
                avgGain = sum / 14;
                sum = 0;
                for (var i = 0; i < lossCollection.length; i++) {
                    sum += lossCollection[i];
                }
                avgLoss = sum / 14;
                if(avgLoss==0)
                    return 100;
                else if(avgGain==0)
                    return 0;
                else{
                    var RS = avgGain / avgLoss;
                    var RSI = 100 - (100 / (1 + RS));
                    return RSI;
                }
            }
            else if (nums.length == (period + 1)) {
                if (nums[nums.length - 1] > nums[nums.length - 2]) {
                    avgGain = (avgGain * 13 + (nums[nums.length - 1] - nums[nums.length - 2]))/14;
                    avgLoss = avgLoss * 13 / 14;
                }
                else if (nums[nums.length - 1] < nums[nums.length - 2]) {
                    avgLoss = (avgLoss * 13 + (nums[nums.length - 2] - nums[nums.length - 1])) / 14;
                    avgGain = avgGain * 13 / 14;
                }
                else {
                    avgLoss = avgLoss * 13 / 14;
                    avgGain = avgGain * 13 / 14;
                }
                if (avgLoss == 0)
                    return 100;
                else if (avgGain == 0)
                    return 0;
                else {
                    var RS = avgGain / avgLoss;
                    var RSI = 100 - (100 / (1 + RS));
                    return RSI
                }
            }
            else
                return null;
        }
    }

    self.movingAverage = function (period) {
        var nums = [];
        return function (num) {
            nums.push(num);
            if (nums.length > period)
                nums.splice(0, 1);  // remove the first element of the array
            var sum = 0;
            for (var i in nums)
                sum += nums[i];
            var n = period;
            if (nums.length < period)
                n = nums.length;
            return (sum / n);
        }
    }

    self.CalculateEMA = function(todaysPrice,numberOfDays,EMAYesterday){
        var k = 2 / (numberOfDays + 1);
        return (todaysPrice * k + EMAYesterday * (1 - k));
    }

    self.getLastestUpdate = function () {
        var url = "../Services/StockDashboardService.svc/GetQuoteLatest/{symbol}?c={connectionString}";
        url = url.replace("{symbol}", encodeURIComponent(self.currentTickerSymbol));
        url = url.replace("{connectionString}", encodeURIComponent(self.connectionString));


        $.ajax({
            type: "GET",
            url: url,
            dataType: "jsonp",
            crossDomain: true,
            success: function (results) {
                var resultArray = results.split(",");
                self.currentStockPrice(resultArray[0]);
                var stockDiff = resultArray[1].replace(" ", "").replace("\n", "");
                var stockDiffRatio = resultArray[2].replace(" ", "").replace("\n", "");
                $(".TrendIndicator").show();
                if (resultArray[1] > 0) {
                    self.isPositiveResult(true);
                    stockDiff = stockDiff.replace("+", "");
                    stockDiffRatio = stockDiffRatio.replace("+", "");
                    $(".trendNum").css("color", "green");
                    $(".TrendRatio").css("color", "green");
                }
                else if (resultArray[1] < 0) {
                    self.isPositiveResult(false);
                    stockDiff = stockDiff.replace("-", "");
                    stockDiffRatio = stockDiffRatio.replace("-", "");
                    $(".trendNum").css("color", "red");
                    $(".TrendRatio").css("color", "red");
                }
                else {
                    self.isPositiveResult(null);
                    $(".TrendIndicator").hide();
                    $(".trendNum").css("color", "black");
                    $(".TrendRatio").css("color", "black");
                }
                self.stockDifferenceRatio("(" + stockDiffRatio.replace(/"/g, "") + ")");
                self.stockDifference(stockDiff);
            },
            error: function (result) {
                alert('error!');

            }
        });
    }

    self.errorHandler = function () {
        alert('Error');
    };

    self.hideAll = function () {
        $("#CommandTimeLine").hide();
        $("#CommandCharts").hide();
        $("#selection").hide();
        $("#tiemSelection").hide();
    }

    self.showAll = function () {

    }

};

function base64Encode(str) {
    var CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    var out = "", i = 0, len = str.length, c1, c2, c3;
    while (i < len) {
        c1 = str.charCodeAt(i++) & 0xff;
        if (i == len) {
            out += CHARS.charAt(c1 >> 2);
            out += CHARS.charAt((c1 & 0x3) << 4);
            out += "==";
            break;
        }
        c2 = str.charCodeAt(i++);
        if (i == len) {
            out += CHARS.charAt(c1 >> 2);
            out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
            out += CHARS.charAt((c2 & 0xF) << 2);
            out += "=";
            break;
        }
        c3 = str.charCodeAt(i++);
        out += CHARS.charAt(c1 >> 2);
        out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
        out += CHARS.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
        out += CHARS.charAt(c3 & 0x3F);
    }
    return out;
}
function getQuerystring(key, default_) {

    if (default_ == null) default_ = "";
    key = key.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regex = new RegExp("[\\?&]" + key + "=([^&#]*)");
    var qs = regex.exec(window.location.href);
    if (qs == null)
        return default_;
    else
        return qs[1];
}
function htmlEscape(str) {
    return String(str)
            .replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/ /g, '&nbsp;')
            .replace(/\n/g, '<br />');
}


Date.prototype.addDays = function(days) {
    this.setDate(this.getDate() + parseInt(days));
    return this;
};


var dateFormat = function () {
    var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
        timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
        timezoneClip = /[^-+\dA-Z]/g,
        pad = function (val, len) {
            val = String(val);
            len = len || 2;
            while (val.length < len) val = "0" + val;
            return val;
        };

    // Regexes and supporting functions are cached through closure
    return function (date, mask, utc) {
        var dF = dateFormat;

        // You can't provide utc if you skip other args (use the "UTC:" mask prefix)
        if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
            mask = date;
            date = undefined;
        }

        // Passing date through Date applies Date.parse, if necessary
        date = date ? new Date(date) : new Date;
        if (isNaN(date)) throw SyntaxError("invalid date");

        mask = String(dF.masks[mask] || mask || dF.masks["default"]);

        // Allow setting the utc argument via the mask
        if (mask.slice(0, 4) == "UTC:") {
            mask = mask.slice(4);
            utc = true;
        }

        var _ = utc ? "getUTC" : "get",
            d = date[_ + "Date"](),
            D = date[_ + "Day"](),
            m = date[_ + "Month"](),
            y = date[_ + "FullYear"](),
            H = date[_ + "Hours"](),
            M = date[_ + "Minutes"](),
            s = date[_ + "Seconds"](),
            L = date[_ + "Milliseconds"](),
            o = utc ? 0 : date.getTimezoneOffset(),
            flags = {
                d: d,
                dd: pad(d),
                ddd: dF.i18n.dayNames[D],
                dddd: dF.i18n.dayNames[D + 7],
                m: m + 1,
                mm: pad(m + 1),
                mmm: dF.i18n.monthNames[m],
                mmmm: dF.i18n.monthNames[m + 12],
                yy: String(y).slice(2),
                yyyy: y,
                h: H % 12 || 12,
                hh: pad(H % 12 || 12),
                H: H,
                HH: pad(H),
                M: M,
                MM: pad(M),
                s: s,
                ss: pad(s),
                l: pad(L, 3),
                L: pad(L > 99 ? Math.round(L / 10) : L),
                t: H < 12 ? "a" : "p",
                tt: H < 12 ? "am" : "pm",
                T: H < 12 ? "A" : "P",
                TT: H < 12 ? "AM" : "PM",
                Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
                o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
                S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
            };

        return mask.replace(token, function ($0) {
            return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
        });
    };
}();

// Some common format strings
dateFormat.masks = {
    "default": "ddd mmm dd yyyy HH:MM:ss",
    shortDate: "m/d/yy",
    mediumDate: "mmm d, yyyy",
    longDate: "mmmm d, yyyy",
    fullDate: "dddd, mmmm d, yyyy",
    shortTime: "h:MM TT",
    mediumTime: "h:MM:ss TT",
    longTime: "h:MM:ss TT Z",
    isoDate: "yyyy-mm-dd",
    isoTime: "HH:MM:ss",
    isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
    isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
};

// Internationalization strings
dateFormat.i18n = {
    dayNames: [
        "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
    ],
    monthNames: [
        "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
        "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
    ]
};

Date.prototype.format = function (mask, utc) {
    return dateFormat(this, mask, utc);
};